/**
 * @author Qiang Fu
 */
public class Bar extends Spring {
    /**
     * A relatively large k constant to make the spring hard to expand or shrink to behave like a bar 
     */
    private static final double KCONST = 2.5;
    /**
     * A damping force is applied to masses to stop oscillation, whose amplitude is proportional to
     * the mass velocity but with opposite direction
     */
    private static final double DAMPCONST = 0.5;
    /**
     * The oscillation is detected once the change in bar length is greater than this value 
     */
    private static final double THRESHOLD = 1;
    
    /**
     * Constructor for this class
     * @param start Mass on start end of the muscle
     * @param end Mass on end of muscle
     * @param length Rest length of the bar
     * @param kVal k value associated with the spring/bar
     */
    public Bar(Mass start, Mass end, double length, double kVal) {
        super(start, end, length, KCONST);
        // TODO Auto-generated constructor stub
    }
  
    /**
     * @param canvas The simulation where this is running
     * @param dt Time changes
     */
    public void update(Simulation canvas, double dt) {
        super.update(canvas, dt);
        
        /**
         * Get the velocity of each mass
         */
        Force startMassVelocity = getMyStart().getVelocity();
        Force endMassVelocity = getMyEnd().getVelocity();
        /**
         * The distances on x and y axises
         */
        double dx = getMyStart().getCenter().getX() 
                - getMyEnd().getCenter().getX();
        double dy = getMyStart().getCenter().getY() 
                - getMyEnd().getCenter().getY();
        
        /**
         * Detect the oscillation and apply the damping force
         */
        if (Force.distanceBetween(dx, dy) < getMyLength() - THRESHOLD 
                || Force.distanceBetween(dx, dy) > getMyLength() + THRESHOLD) {
            /**
             * The damping force to be applied to the masses. Define the direction towards the 
             * center of the bar as the direction of the force
             */
            Force dampStart = new Force(Force.angleBetween(-dx, -dy), 0);
            Force dampEnd = new Force(Force.angleBetween(dx, dy), 0);
            /**
             * Get the oscillation velocity by projecting the mass velocity along the direction 
             * of the bar
             */
            double velocityStartmassBar = 
                    -startMassVelocity.getRelativeMagnitude(dampStart);
            double velocityEndmassBar = 
                    -endMassVelocity.getRelativeMagnitude(dampEnd);
            /**
             * The magnitude of the damping force is proportional to the oscillation velocity
             */
            dampStart.setMagnitude(-velocityStartmassBar * DAMPCONST);
            dampEnd.setMagnitude(-velocityEndmassBar * DAMPCONST);
            
            getMyStart().applyForce(dampStart);
            getMyEnd().applyForce(dampEnd);
        }  
    }
}
